#pragma once
#include <assert.h>
#include <cstring>
//////////////////////////////////////////////////////////////////////////////
//				德州扑克游戏全局数据结构定义
//////////////////////////////////////////////////////////////////////////////
#define TOTAL_OF_CARDS		7	// 德州扑克一手牌为7张
#define TOTAL_OF_HANDS		5	// 7张中选出5张最优牌

#define USHORT unsigned short
#define UCHAR unsigned char

typedef unsigned short CardType;
enum HAND_CARD_TYPE //手牌的类型
{
	HAND_CARD_TYPE_PAIR_A = 1,   //手牌为AA
	HAND_CARD_TYPE_FLUSH_AK,   //同花AK
	HAND_CARD_TYPE_FLUSH_AQ_OR_AJ, //同花AQ或者AJ
	HAND_CARD_TYPE_UNFLUSH_AK,		//非同花的AK
	HAND_CARD_TYPE_PAIR_J_TO_K,		//对J到对K
	HAND_CARD_TYPE_UNFLUSH_AQ_OR_AJ, //非同花AQ或者AJ
	HAND_CARD_TYPE_PAIR_2_TO_10,		//对2到对10
	HAND_CARD_TYPE_FLUSH_STRAIGHT,	//手牌的同花顺子
	HAND_CARD_TYPE_FLUSH,		//手牌的同花
	HAND_CARD_TYPE_STRAIGHT,	//手牌的顺子,即为两张点数连续的牌，注意：A,2为顺子，AK也为顺子
	HAND_CARD_TYPE_PIE		//杂牌,11
};
//////////////////////////////////////////////////////////////////////////////
// 定义单张牌的数据结构
//////////////////////////////////////////////////////////////////////////////
struct POKERCARD
{
	union
	{
		USHORT card;
		struct { UCHAR value, color; } split;
	}S_un;
};

// 最好的五张牌
struct BESTHAND
{
	UCHAR nHandType;
	POKERCARD m_BestHand[TOTAL_OF_HANDS];
};

// 52张牌数组定义
//static const USHORT GLOBAL_POKER[52] = 
//{
//	0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, 0x0108, 0x0109, 0x010A, 0x010B, 0x010C, 0x010D, 0x010E,//方块
//	0x0202, 0x0203, 0x0204, 0x0205, 0x0206, 0x0207, 0x0208, 0x0209, 0x020A, 0x020B, 0x020C, 0x020D, 0x020E,//梅花
//	0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307, 0x0308, 0x0309, 0x030A, 0x030B, 0x030C, 0x030D, 0x030E,//红桃
//	0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, 0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x040D, 0x040E//黑桃
//};

#define p_card		S_un.card
#define p_color		S_un.split.color
#define p_value		S_un.split.value
//////////////////////////////////////////////////////////////////////////////
// 四种花色定义
//////////////////////////////////////////////////////////////////////////////
enum
{	// 方块			梅花	 红桃		黑桃
	FANG_KUAI = 1, MEI_HUA, HONG_TAO, HEI_TAO
};

//////////////////////////////////////////////////////////////////////////////
// 牌型定义
//////////////////////////////////////////////////////////////////////////////
enum
{
	TYPE_PIE_CARD = 1,	// 杂牌		Pie Card
	TYPE_HIGH_CARD,		// 高牌		High Card
	TYPE_PAIR,			// 一对		Pair
	TYPE_TWO_PAIRS,		// 二对		Two Pairs
	TYPE_THREE_KIND,	// 三条		Three of a kind
	TYPE_STRAIGHT,		// 顺子		Straight
	TYPE_FLUSH,			// 同花		Flush
	TYPE_FULL_HOUSE,	// 葫芦		Full House
	TYPE_FOUR_KIND,		// 四条		Four of a Kind
	TYPE_STRAIGHT_FLUSH,// 同花顺	Straight Flush
	TYPE_ROYAL_FLUSH	// 皇家同花顺Royal Flush
};
//////////////////////////////////////////////////////////////////////////////
// 统计同样牌值数量时使用的结构
//////////////////////////////////////////////////////////////////////////////
struct SAME_CARDS_COUNT{
	UCHAR pos, count;
};

// 比较两个数值的大小
#define COMP_VALUE(a,b)	((a) == (b) ? 0 : ((a) < (b) ? -1 : 1))

//////////////////////////////////////////////////////////////////////////////
// 牌型字符串定义
//////////////////////////////////////////////////////////////////////////////

#ifndef __POKER_GLOBAL_STRING__
#define	__POKER_GLOBAL_STRING__

#define show_poker_color(n)		g_color[n-1]
#define show_hands_type_cn(n)	g_handstype_string_cn[n-1]

// 牌型字符串中文
static const char * const g_handstype_string_cn[] =
{
	"杂牌",
	"高牌",
	"对子",
	"两对",
	"三条",
	"顺子",
	"同花",
	"葫芦",
	"四条",
	"同花顺",
	"皇家同花顺"
};

static const char * const g_color[] =
{
	"方块",  // 方
	"梅花", // 梅
	"红桃", // 红
	"黑桃" // 黑
};

static const char * const g_val[] =
{
	"1",
	"2",
	"3",
	"4",
	"5",
	"6",
	"7",
	"8",
	"9",
	"10",
	"J",
	"Q",
	"K",
	"A"
};


#define SMALLBLIND 10
//#define GAMEOVERTIEMEVENT 100
//#define GAMECHIPINEVENT 1000
//#define TABLESTANDCHECK 5000
//#define GAMEUSERCLOSE 10000
//#define GAMESTART  3

#define USERPLAYCARD 3
#define USERSIT 2
#define USERNOSIT 1
#define USERINI 0
#endif

//////////////////////////////////////////////////////////////////////////////
// PokerHands 一手牌，在德州扑克中，通常7张为一手牌
//////////////////////////////////////////////////////////////////////////////
class CPokerHands
{
public:
	CPokerHands(void)
	{
		Initialize();
	};
private:
	// 原始7张牌
	POKERCARD m_Cards[TOTAL_OF_CARDS];
	// 优选出的最大5张牌
	POKERCARD *m_pHands;
	// 同样牌值计数结构
	SAME_CARDS_COUNT m_SameCards[3];
	// 花色统计数组, 记录7张牌中, 4种花色各自数量
	UCHAR m_ColorCount[4];
	// 记录是否同花, 0 值不是同花, 其他表示同花的花色
	UCHAR m_nFlushColor;
	// 同样牌值计数器
	UCHAR m_nSameCount;
	// 对牌统计 7张牌有时会出现3个对子
	UCHAR m_nPairCount ;	
	// 三条统计 7张牌有时会出现2个三条
	UCHAR m_nThreeKindCount;
	// 最优的5张牌的类型
	UCHAR m_nTypeHands ;
public:
	///////////////////////////////////////////////////////////////////////////
	// 对外部调用公开的函数定义

	///////////////////////////////////////////////////////////////////////////
	// 获取牌型 The Poker Hand Type
	///////////////////////////////////////////////////////////////////////////
	int GetHandsType(void) {return m_nTypeHands;};
	///////////////////////////////////////////////////////////////////////////
	// 检测牌型并优选出最大的5张牌
	///////////////////////////////////////////////////////////////////////////
	void CheckHandsType(unsigned short *pHand)
	{
		// 断言是否SetHands设置过牌数据
		if(m_Cards[0].p_card==0)
			return;
		//assert(m_Cards[0].p_card != 0);
		m_pHands = (POKERCARD *)pHand;

		// 德州扑克算法步骤
		CountFlush();		// 2. 统计牌中各花色的数量，检测是否有5张同花色的牌
		SortCards();		// 1. 将牌从大到小依次排列，共7张
		CountSameCards();	// 3. 统计牌中复数牌的数量，例如对子、三条或四条
							// 4. 依次从最大牌型到最小牌型进行检测, 并选出最优的5张
		if(CheckStraightFlush())return;	// 同花顺 Royal Flush & Straight Flush
		if(CheckFourCard())		return;	// 四条 Four of a kind
		if(CheckFullHouse())	return;	// 葫芦 Full House
		if(CheckFlush())		return;	// 同花 Flush
		if(CheckStraight())		return;	// 顺子 Straight
		if(CheckThreeCard())	return;	// 三条 Three of a kind
		if(CheckTwoPair())		return;	// 两对 Two Pair
		if(CheckPair())			return;	// 一对 Pair
		if(CheckHighCard())		return;	// 高牌 High Card
		assert(0);						// 最差应为 TYPE_PIE_CARD，否则Big Bug
	}	
int GetHandCardTypeWithCard(USHORT card1,USHORT card2)
	{
		int nRet=-1;
		USHORT sColor=0xFF00;
		USHORT sValue=0x00FF;
		USHORT sA=0x000E;//值为A
		USHORT sJ=0x000B;//值为J
		USHORT s2=0x0002;//值为2
		USHORT sF=0x0100;//颜色为方块
		USHORT sH=0x0400;//颜色为黑桃
		bool bIsFlush=false;
		bool bIsStraight=false;
		bool bIsPair=false;
		bool bIsCardValid=false;
		
		//先排序，先按值排序，再按花色排序，保证card1一定大于card2
		USHORT tmp=card1;
		if( (card1 & sValue) < (card2 & sValue)) //先按值排序
		{
			tmp=card1;
			card1=card2;
			card2=tmp;
		}
		if( (card1 & sValue) == (card2 & sValue) )//若值相等，则按花色排序
		{
	        bIsPair=true;//对子
	        if((card1 & sColor) < (card2 & sColor))
	        {
				tmp=card1;
	            card1=card2;
	            card2=tmp;
	        }
	        
		}
		//检测手牌的值是否有效
		if( ((card1 & sColor)<=sH) && ((card1 & sValue)<=sA))
			bIsCardValid=true;
		if( (bIsCardValid && (card2 & sColor)>=sF)  && ((card2 & sValue)>=s2) )
			bIsCardValid=true;
		if(!bIsCardValid)
	    {
			return nRet;
	    }
			
			
		//做手牌统计
		if(!bIsPair && (card1 & sColor) == (card2 & sColor))//手牌的同花
			bIsFlush=true;
		int nDiffer =(int)((card1 & sValue) - (card2 & sValue));
		if(!bIsPair && (nDiffer==1 || nDiffer==12))//手牌的顺子，注意，此处 A与2 算为一个顺子
			bIsStraight=true;

	    if(!bIsFlush && !bIsStraight && !bIsPair)
	    {
	        if( (card1 & sValue)== sA && ((card2 & sValue)>=sJ && (card2 & sValue)<sA) )
	            return HAND_CARD_TYPE_UNFLUSH_AQ_OR_AJ;
	        return HAND_CARD_TYPE_PIE;
	    }

	    if(bIsFlush)//同花
	    {
	        if((card1 & sValue)== sA)
	        {
	            if((card2 & sValue)==(sA-1))
	                return HAND_CARD_TYPE_FLUSH_AK;
	            if((card2 & sValue)>=sJ && (card2 & sValue)<sA)
	                return HAND_CARD_TYPE_FLUSH_AQ_OR_AJ;
	        }
	        if(bIsStraight)
	            return HAND_CARD_TYPE_FLUSH_STRAIGHT;
	        return HAND_CARD_TYPE_FLUSH;
	    }

	    if(bIsStraight)
	    {
	        if((card1 & sValue)== sA && (card2 & sValue)==(sA-1) )
	            return HAND_CARD_TYPE_UNFLUSH_AK; 
	        return HAND_CARD_TYPE_STRAIGHT;  
	    }
			
		if(bIsPair)//对子
		{
			if((card1 & sValue)>=s2 && (card1 & sValue)<sJ)
				return HAND_CARD_TYPE_PAIR_2_TO_10;//对2到对10
			if((card1 & sValue)>=sJ && (card1 & sValue)<sA)
				return HAND_CARD_TYPE_PAIR_J_TO_K;//对J到对K
			if((card1 & sValue)==sA)
				return HAND_CARD_TYPE_PAIR_A;//对A
		}
	    
	    return nRet;
	}	
	///////////////////////////////////////////////////////////////////////////
	// 初始化内部所有变量，重复利用对象时可调用
	///////////////////////////////////////////////////////////////////////////
	void Initialize(void)
	{
		m_nFlushColor = 0;		// 初始化同花标志
		m_nSameCount = 0;		// 复数牌数量
		m_nPairCount = 0;		// 对牌数量
		m_nThreeKindCount = 0;	// 三条数量
		m_nTypeHands = 0;		// 牌型，最小牌型应从1开始 TYPE_PIE_CARD
		m_pHands = NULL;

		// 初始化各种数组
		memset(m_Cards, 0, sizeof(m_Cards));
		memset(m_ColorCount, 0, sizeof(m_ColorCount));
		memset(m_SameCards, 0, sizeof(m_SameCards));
	}
	///////////////////////////////////////////////////////////////////////////
	// 设置牌值
	///////////////////////////////////////////////////////////////////////////
	void SetHands(USHORT c1, USHORT c2, const USHORT *pBoardCard)
	{
		m_Cards[0].p_card = c1;		
		m_Cards[1].p_card = c2;
		m_Cards[2].p_card = pBoardCard[0];
		m_Cards[3].p_card = pBoardCard[1];
		m_Cards[4].p_card = pBoardCard[2];
		m_Cards[5].p_card = pBoardCard[3];
		m_Cards[6].p_card = pBoardCard[4];
	}
	///////////////////////////////////////////////////////////////////////////
	void SetHands(UCHAR *hands)
	{
		for(int i = 0; i < TOTAL_OF_CARDS; i ++)
		{
			m_Cards[i].p_color = hands[i*2];
			m_Cards[i].p_value = hands[i*2+1];

			// 断言牌值范围 2 - 14
			assert(m_Cards[i].p_value >= 2 && m_Cards[i].p_value <= 14);
			// 断言牌面花色 1 - 4 黑红梅方
			assert(m_Cards[i].p_color >= 1 && m_Cards[i].p_color <= 4);
		}
	}
private:
	///////////////////////////////////////////////////////////////////////////
	// 内部辅助函数定义开始

	///////////////////////////////////////////////////////////////////////////
	// 将一组牌从大到小进行排序 Ace = 14
	///////////////////////////////////////////////////////////////////////////
	void SortCards(void)
	{
		USHORT temp, max;
		for(int i = 0; i < TOTAL_OF_CARDS; i ++)
		{
			max = i;
			if(m_Cards[i].p_card == 0) //如果牌非法返回
				return;
			for(int j = i + 1; j < TOTAL_OF_CARDS; j ++)
			{	
				if(m_Cards[j].p_card == 0)
					continue;
				if((m_Cards[j].p_value > m_Cards[max].p_value))
					max = j;
				/////////// 有同花者放前
				if(m_nFlushColor != 0 && m_Cards[j].p_value == m_Cards[max].p_value
					&& m_Cards[j].p_color==m_nFlushColor)
					max = j;
				///////////
			}
			if(max != i)
			{
				temp = m_Cards[i].p_card;
				m_Cards[i].p_card = m_Cards[max].p_card;
				m_Cards[max].p_card = temp;
			}
		}
	}
	///////////////////////////////////////////////////////////////////////////
	// 检查一组牌中同样花色的牌是否大于5张
	///////////////////////////////////////////////////////////////////////////
	void CountFlush(void)
	{
		for(int i = 0; i < TOTAL_OF_CARDS; i ++)
		{
			if(m_Cards[i].p_card == 0)
				continue;
			if(++m_ColorCount[m_Cards[i].p_color-1] >= TOTAL_OF_HANDS)
			{
				m_nFlushColor = m_Cards[i].p_color;
				break;// 牌面包含同花
			}
		}
	}
	///////////////////////////////////////////////////////////////////////////
	// 统计一组7张牌中, 对子，三条或四条的数量
	///////////////////////////////////////////////////////////////////////////
	void CountSameCards(void)
	{
		int i, nCount = 0;
		UCHAR start = 0;

		for(i = 1; i < TOTAL_OF_CARDS; i ++)
		{
			if(m_Cards[i].p_card == 0)
				continue;
			if(nCount == 0)
			{
				nCount = 1;
				start = m_Cards[i-1].p_value;
			}
			if(start == m_Cards[i].p_value)
				nCount++;
			else
			{
				if(nCount >= 2)
					set_same_cards(i, nCount);
				nCount = 0;
			}
		}
		if(nCount >= 2)
			set_same_cards(i, nCount);
	}
	///////////////////////////////////////////////////////////////////////////
	// 记录对子、三条、四条所在的位置及数量， 方便CountSameCards调用
	///////////////////////////////////////////////////////////////////////////
	void set_same_cards(int nPos, int nCount)
	{
		m_SameCards[m_nSameCount].pos = nPos - nCount;	// 位置减数量，得出对子起始位置
		m_SameCards[m_nSameCount].count = nCount;
		assert(m_nSameCount < 3);	// 断言一组牌中不可能超过3组对子
		m_nSameCount ++;		// 总的对牌计数
		switch(nCount)
		{
		case 2:
			m_nPairCount ++;	// 对子计数
			break;
		case 3:
			m_nThreeKindCount ++;// 三条计数
			break;
		};
	}
	///////////////////////////////////////////////////////////////////////////
	// 检查是否顺子		bFlush = true 检查时是否考虑花色问题
	// 返回 = -1 说明不是顺子
	// 返回 >= 4 顺子最右边的牌在CARDS中的位置, 但Ace例外,Ace是大牌, 排在最左边
	///////////////////////////////////////////////////////////////////////////
	int IsStraight(bool bFlush = true)
	{
		int i = 0, nCount = 0 ;
		UCHAR pos = 0;
		while(i ++ < TOTAL_OF_CARDS-1)
		{
			if(m_Cards[i-1].p_card == 0)
				return -1;
			if(nCount == 0)
			{
				if(bFlush && m_Cards[i-1].p_color != m_nFlushColor)
					continue; // 如果顺子起始牌的花色是同花, 则SKIP

				nCount = 1;
				pos = m_Cards[i-1].p_value;
			}
			if(bFlush && m_Cards[i].p_color != m_nFlushColor)	// 花色是否一样
				continue;
			
			// 如果顺子起始牌, 与后而的N张牌够成顺子,则COUNT++计数
			if(pos == m_Cards[i].p_value + nCount)
			{
				// 检测 A，2，3，4，5
				if(++nCount == 4 && pos == 5 && m_Cards[0].p_value == 14)
				{
					if(!bFlush || m_Cards[0].p_color == m_nFlushColor)
						return 100 + i;
				}
				// 够5张即是顺子
				if(nCount >= TOTAL_OF_HANDS) return i;
			}else
			{
				if(m_Cards[i].p_value != m_Cards[i-1].p_value)
					nCount = 0;
				//if(pos == 14 && m_Cards[i-1].p_value == 5 && m_Cards[i].p_value == 5)
				//	nCount = 0;
			}
		}
		return -1;
	}
private:
	///////////////////////////////////////////////////////////////////////////
	// 提取优选牌算法函数定义开始

	///////////////////////////////////////////////////////////////////////////
	// 提取同花顺子,或顺子  bFlush = true 同花选项
	// 从m_Cards 7 张牌中筛选出最大的5张顺子, 如果是A,2,3,4,5 则Ace放在最右边
	// 参数 bFlush = true 只筛选同花, bFlush = false 忽略花色
	///////////////////////////////////////////////////////////////////////////
	void FilterStraight(int nPos, bool bFlush = true)
	{
		int handpos = TOTAL_OF_HANDS - 1;	// handpos 从数组的最右端依次放入优牌

		// nPos > 100 的情况为最小顺子,例: A,2,3,4,5, 否则为普通顺子
		if(nPos > 100)
		{
			nPos -= 100;
			int nAcePos = 0;

			if(bFlush)	// 如果是同花,则需循环获取到同花色的那张Ace
			{
				for(int i = 0; i < 2; i ++)
				{
					if(m_Cards[i].p_color == m_nFlushColor)
					{
						nAcePos = i;
						break;
					}
				}
			}
			// 获取A,2,3,4,5中的Ace牌, 此时Ace为小牌, 放入数组中的最右边
			m_pHands[handpos--].p_card = m_Cards[nAcePos].p_card;
		}
		// 开始循环, 从右向左提取顺子
		while(handpos >= 0)
		{
			if(bFlush)// bFlush = true 取同花顺子
			{
				if(m_Cards[nPos].p_color != m_nFlushColor)	// 花色不同 SKIP
				{
					nPos --; 
					continue;
				}
			}else	// bFlush = false 取普通顺子
			{
				if(handpos < TOTAL_OF_HANDS - 1 &&
					m_pHands[handpos+1].p_value == m_Cards[nPos].p_value)
				{
						nPos --;
						continue;
				}
			}
			// 提取顺子
			m_pHands[handpos--].p_card = m_Cards[nPos--].p_card;
		}
		// 如果顺子的第一张为A, 则为皇家同花顺
		if(bFlush && m_pHands[0].p_value == 14)
			m_nTypeHands = TYPE_ROYAL_FLUSH;
	}
	///////////////////////////////////////////////////////////////////////////
	// 提取四条 Four of a Kind
	///////////////////////////////////////////////////////////////////////////
	void FilterFourCard(int nPos)
	{
		// 获取4条的4张牌
		m_pHands[0].p_card = m_Cards[nPos].p_card ;
		m_pHands[1].p_card = m_Cards[nPos+1].p_card ;
		m_pHands[2].p_card = m_Cards[nPos+2].p_card ;
		m_pHands[3].p_card = m_Cards[nPos+3].p_card ;

		// 获取四条牌型的第5张 Kickers 起脚牌
		nPos = nPos == 0 ? 4 : 0;
		m_pHands[4].p_card = m_Cards[nPos].p_card;
	}
	///////////////////////////////////////////////////////////////////////////
	// 辅助函数, 找出并取出第一组三条,从左至右放入优选数组
	///////////////////////////////////////////////////////////////////////////
	void FilterFirstThreeCard(void)
	{
		int nPos = -1;
		// 找出第一组三条所在的位置
		for(int i = 0; i < m_nSameCount; i ++)
		{
			if(m_SameCards[i].count == 3)
			{
				nPos = m_SameCards[i].pos;
				break;
			}
		}
		assert(nPos != -1);
		// 循环3次, 取出三条
		for(int i = 0; i < 3; i ++)
			m_pHands[i].p_card = m_Cards[nPos+i].p_card;
	}
	///////////////////////////////////////////////////////////////////////////
	// 提取葫芦 Full House
	///////////////////////////////////////////////////////////////////////////
	void FilterFullHouse(void)
	{
		int nPos = 0;

		// 取Full House牌型中的第一组三条
		FilterFirstThreeCard();

		// m_nThreeKindCount > 1 说明是两个三条, 否则是三条加两对或一对
		if(m_nThreeKindCount > 1)
		{
			// 取得第二组三条的前两张
			nPos = m_SameCards[1].pos;
			m_pHands[3].p_card = m_Cards[nPos].p_card;
			m_pHands[4].p_card = m_Cards[nPos+1].p_card;
		}else
		{
			// 找出对子所在位置
			for(int i = 0; i < m_nSameCount; i ++)
			{
				if(m_SameCards[i].count == 2)
				{
					nPos = m_SameCards[i].pos;
					break;
				}
			}
			// 取出最大对子的两张牌
			m_pHands[3].p_card = m_Cards[nPos].p_card;
			m_pHands[4].p_card = m_Cards[nPos+1].p_card;
		}
	}
	///////////////////////////////////////////////////////////////////////////
	// 提取同花 Flush, 从左至向，从大到小，选出5张同花
	///////////////////////////////////////////////////////////////////////////
	void FilterFlush(void)
	{
		int nPos = 0;
		for(int i = 0; i < TOTAL_OF_CARDS && nPos < TOTAL_OF_HANDS; i ++)
		{
			if(m_Cards[i].p_card == 0)
				continue;
			if(m_Cards[i].p_color == m_nFlushColor)
				m_pHands[nPos++].p_card = m_Cards[i].p_card;
		}
	}
	///////////////////////////////////////////////////////////////////////////
	// 提取三条 Three of a kind
	///////////////////////////////////////////////////////////////////////////
	void FilterThreeCard(void)
	{
		FilterFirstThreeCard();

		UCHAR ch = m_pHands[0].p_value;
		for(int i = 0, n = 3; i < TOTAL_OF_CARDS && n < TOTAL_OF_HANDS; i ++)
		{
			if(m_Cards[i].p_card == 0)
				continue;
			if(ch != m_Cards[i].p_value)
				m_pHands[n++].p_card = m_Cards[i].p_card;	
		}
	}
	///////////////////////////////////////////////////////////////////////////
	// 提取两对 Two pair
	///////////////////////////////////////////////////////////////////////////
	void FilterTwoPair(void)
	{
		assert(m_SameCards[0].count == 2);
		assert(m_SameCards[1].count == 2);

		// 取出第一对
		int nPos = m_SameCards[0].pos;
		m_pHands[0].p_card = m_Cards[nPos].p_card;
		m_pHands[1].p_card = m_Cards[nPos+1].p_card;
		
		// 取出第二对
		nPos = m_SameCards[1].pos;
		m_pHands[2].p_card = m_Cards[nPos].p_card;
		m_pHands[3].p_card = m_Cards[nPos+1].p_card;

		// 取出最大牌 Two Pair中的Kickers起脚牌
		for(int i = 0; i < TOTAL_OF_CARDS; i ++)
		{
			if(m_Cards[i].p_card != 0 && m_Cards[i].p_value != m_pHands[0].p_value	&& m_Cards[i].p_value != m_pHands[2].p_value)
			{
				m_pHands[4].p_card = m_Cards[i].p_card;
				break;
			}
		}
	}
	///////////////////////////////////////////////////////////////////////////
	// 提取对子 Pair
	///////////////////////////////////////////////////////////////////////////
	void FilterPair(void)
	{
		assert(m_SameCards[0].count == 2);
		// 取出第一对
		int nPos = m_SameCards[0].pos;
		m_pHands[0].p_card = m_Cards[nPos].p_card;
		m_pHands[1].p_card = m_Cards[nPos+1].p_card;

		// 取出最大牌 Pair中三张的Kickers起脚牌
		for(int i = 0, n = 2; i < TOTAL_OF_CARDS && n < TOTAL_OF_HANDS; i ++)
		{
			if(m_Cards[i].p_card != 0 && m_Cards[i].p_value != m_pHands[0].p_value)
				m_pHands[n++].p_card = m_Cards[i].p_card;
		}
	}
	///////////////////////////////////////////////////////////////////////////
	// 提取高牌 High Card
	///////////////////////////////////////////////////////////////////////////
	void FilterHighCard(void)
	{
		// 从大到小 复制前5张牌
		for(int i = 0; i < TOTAL_OF_HANDS; i ++)
		{
			if(m_Cards[i].p_card == 0)
				continue;
			m_pHands[i].p_card = m_Cards[i].p_card;
		}

		// 如果最大的牌大于J, 则为类型高牌 High Card, 否则为杂牌 Pie Card
		if(m_pHands[0].p_value < 11)
			m_nTypeHands = TYPE_PIE_CARD;
	}
private:
	///////////////////////////////////////////////////////////////////////////
	// 检测优选牌算法函数定义开始

	///////////////////////////////////////////////////////////////////////////
	// 检查是否同花顺 Royal Fulsh
	///////////////////////////////////////////////////////////////////////////
	bool CheckStraightFlush(void)
	{
		if(m_nFlushColor == 0)
			return false;

		int nPos = IsStraight(true);
		if(nPos != -1)
		{
			// 缺省为普通同花顺子
			m_nTypeHands = TYPE_STRAIGHT_FLUSH;
			FilterStraight(nPos, true);
			return true;
		}
		return false;
	}
	///////////////////////////////////////////////////////////////////////////
	// 检测是否四条 Four of a Kind
	///////////////////////////////////////////////////////////////////////////
	bool CheckFourCard(void)
	{
		// 循环检测是否包括4条, 防止类似 A,A,A,5,5,5,5 牌型
		for(int i = 0; i < m_nSameCount; i ++)
		{
			if(m_SameCards[i].count == 4)
			{
				assert(m_nSameCount <= 2);	// 4条的情况下，m_nSameCount不应该大于2
				m_nTypeHands = TYPE_FOUR_KIND;
				FilterFourCard(m_SameCards[i].pos);	// 调用Filter程序取出4条,放入优选数组
				return true;
			}
		}
		return false;
	}
	///////////////////////////////////////////////////////////////////////////
	// 检测是否葫芦 Full House
	///////////////////////////////////////////////////////////////////////////
	bool CheckFullHouse(void)
	{
		if(m_nThreeKindCount < 1)
			return false;	// 没有三条, 不能组成Full House
		if(m_nThreeKindCount == 1 && m_nPairCount < 1)
			return false;	// 有三条没对子, 不能组成Full House

		m_nTypeHands = TYPE_FULL_HOUSE;
		FilterFullHouse();
		return true;
	}
	///////////////////////////////////////////////////////////////////////////
	// 检测是否同花 Flush
	///////////////////////////////////////////////////////////////////////////
	bool CheckFlush(void)
	{
		if(m_nFlushColor == 0)
			return false;
		m_nTypeHands = TYPE_FLUSH;
		FilterFlush();

		return true;
	}
	///////////////////////////////////////////////////////////////////////////
	// 检查是否顺子 Straight
	///////////////////////////////////////////////////////////////////////////
	bool CheckStraight(void)
	{
		int nPos = IsStraight(false);
		if(nPos != -1)
		{
			// 缺省为普通同花顺子
			m_nTypeHands = TYPE_STRAIGHT;
			FilterStraight(nPos, false);
			return true;
		}
		return false;
	}
	///////////////////////////////////////////////////////////////////////////
	// 检查是否三条 Three of a kind
	///////////////////////////////////////////////////////////////////////////
	bool CheckThreeCard(void)
	{
		if(m_nThreeKindCount < 1)
			return false;

		m_nTypeHands = TYPE_THREE_KIND;
		FilterThreeCard();

		return true;
	}
	///////////////////////////////////////////////////////////////////////////
	// 检查是否两对 Two pair
	///////////////////////////////////////////////////////////////////////////
	bool CheckTwoPair(void)
	{
		if(m_nPairCount < 2)
			return false;

		m_nTypeHands = TYPE_TWO_PAIRS;
		FilterTwoPair();

		return true;
	}
	///////////////////////////////////////////////////////////////////////////
	// 检查是否对子
	///////////////////////////////////////////////////////////////////////////
	bool CheckPair(void)
	{
		if(m_nPairCount < 1)
			return false;

		m_nTypeHands = TYPE_PAIR;
		FilterPair();

		return true;
	}
	///////////////////////////////////////////////////////////////////////////
	// 检查高牌或杂牌 High Card & Pie Card
	///////////////////////////////////////////////////////////////////////////
	bool CheckHighCard(void)
	{
		m_nTypeHands = TYPE_HIGH_CARD;
		FilterHighCard();

		return true;
	}
};

int CompHandsType(UCHAR t1, const unsigned short *hand1, UCHAR t2, const unsigned short *hand2)
{
	if (t1 > t2)	return 1;	// 牌型比较
	if (t1 < t2)	return -1;
	const POKERCARD *p1 = (const POKERCARD *)hand1;
	const POKERCARD *p2 = (const POKERCARD *)hand2;
	// 比较第一张
	int nRet = COMP_VALUE(p1[0].p_value, p2[0].p_value);
	// 第一张如果不相等，直接返回
	if (nRet != 0)	return nRet;

	int nPos = 0;
	// 第一张相等的情况下，继续比较第2,3,4,5张的牌
	switch (t1)
	{
	case TYPE_HIGH_CARD:		// 高牌		High Card
	case TYPE_PIE_CARD:			// 杂牌		Pie Card
	case TYPE_FLUSH:			// 同花		Flush
		nPos = 1;				// 从第2张开始比较
		break;
	case TYPE_PAIR:				// 一对		Pair
		nPos = 2;				// 从第3张开始比较
		break;
	case TYPE_TWO_PAIRS:		// 二对		Two Pairs
	case TYPE_THREE_KIND:		// 三条		Three of a kind
		nPos = 3;				// 从第4张牌开始比较
		break;
	case TYPE_FULL_HOUSE:		// 葫芦		Full House
	case TYPE_FOUR_KIND:		// 四条		Four of a Kind
		nPos = 4;				// 比较最后一张
		break;
	case TYPE_ROYAL_FLUSH:		// 皇家同花顺Royal Flush
	case TYPE_STRAIGHT_FLUSH:	// 同花顺	Straight Flush
	case TYPE_STRAIGHT:			// 顺子		Straight
		return nRet;
	default:
		return 0;
	}
	// 循环比较第2张以后的牌
	for (int i = nPos; i < TOTAL_OF_HANDS && nRet == 0; i++)
		nRet = COMP_VALUE(p1[i].p_value, p2[i].p_value);
	return nRet;
}
